/*
 * Copyright 2007-2010 Jeremy Brown.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author <a href="http://jeremy-brown.com">Jeremy Brown</a>
 */


package groovy.prefuse.factory

import groovy.prefuse.impl.layout.*

import prefuse.action.*
import prefuse.action.layout.*
import prefuse.action.layout.graph.*
import prefuse.Visualization

public class LayoutFactory extends ActionFactory
{
	private Class klass

	public LayoutFactory(Class klass)
	{
		this.klass = klass
	}
	
	boolean isLeaf()
	{
		return true
	}
    
    public Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException
	{
		builder.context.put("name", attributes.remove("name")) //Layout will be added to Visualization with this name
		
		if(value == null && attributes.layout)
		{
			value = attributes.remove("layout")
		}
		
		if(value instanceof Layout)
		{
			return value
		}

		def buildClass
		if(klass)
		{
			buildClass = klass
		}
		else if(value instanceof Class)
		{
			buildClass = value
			value = null
		}

		def layout = null
		
		if(buildClass instanceof Class && Layout.isAssignableFrom(buildClass))
		{
			if(AxisLabelLayout.equals(buildClass))
			{
				layout = new AxisLabelLayout(builder.pickPrefuseGroup(attributes), attributes.remove("axisLayout"))
			}
			else if(AxisLayout.equals(buildClass))
			{
				layout = new AxisLayout(builder.pickPrefuseGroup(attributes), attributes.remove("dataField"))
			}
			else if(ForceDirectedLayout.equals(buildClass))
			{
				if(attributes.group && attributes.forceSimulator && attributes.enforceBounds)
				{
					layout = new ForceDirectedLayout(builder.pickPrefuseGroup(attributes), attributes.remove("forceSimulator"), attributes.remove("enforceBounds") as boolean)
				}
				else if(attributes.group && attributes.enforceBounds)
				{
					layout = new ForceDirectedLayout(builder.pickPrefuseGroup(attributes), attributes.remove("enforceBounds") as boolean)
				}
				else if(attributes.group)
				{
					layout = new ForceDirectedLayout(builder.pickPrefuseGroup(attributes))
				}
			}
			else if(RandomLayout.equals(buildClass))
			{
				layout = new RandomLayout()
			}
			else if(SpecifiedLayout.equals(value))
			{
				layout = new SpecifiedLayout(builder.pickPrefuseGroup(attributes), attributes.remove("xField"), attributes.remove("yField"))
			}
			else if(StackedAreaChart.equals(value))
			{
				layout = new StackedAreaChart(builder.pickPrefuseGroup(attributes), attributes.remove("dataField"), attributes.remove("columns") as String[])
			}
			
			////////////////////////////////////////////////////////////////////////////////////////
			//DocuBurst extension: http://www.cs.utoronto.ca/~ccollins/research/docuburst/index.html
			//StarburstLayout and WormholeLayout
			////////////////////////////////////////////////////////////////////////////////////////
			else if(builder.getRadialSpaceFillingTreeRegistered() && (ca.utoronto.cs.prefuseextensions.layout.StarburstLayout).equals(buildClass))
			{
				if(attributes.group && attributes.radius != null)
				{
					layout = new ca.utoronto.cs.prefuseextensions.layout.StarburstLayout(builder.pickPrefuseGroup(attributes), attributes.remove("radius"))
				}
				else if(attributes.group)
				{
					layout = new ca.utoronto.cs.prefuseextensions.layout.StarburstLayout(builder.pickPrefuseGroup(attributes))
				}
			}
			else if(builder.getRadialSpaceFillingTreeRegistered() && (ca.utoronto.cs.prefuseextensions.layout.WormholeLayout).equals(buildClass))
			{
				if(attributes.group && attributes.radius != null)
				{
					layout = new ca.utoronto.cs.prefuseextensions.layout.WormholeLayout(builder.pickPrefuseGroup(attributes), attributes.remove("radius"))
				}
				else if(attributes.group)
				{
					layout = new ca.utoronto.cs.prefuseextensions.layout.WormholeLayout(builder.pickPrefuseGroup(attributes))
				}
			}
			
			//constructors that require a group parameter
			else if(
				AggregateLayout.equals(buildClass) ||
				CircleLayout.equals(buildClass) ||
				CollapsedStackLayout.equals(buildClass) ||
				CollapsedSubtreeLayout.equals(buildClass) ||
				GridLayout.equals(buildClass) ||
				BalloonTreeLayout.equals(buildClass) ||
				FruchtermanReingoldLayout.equals(buildClass) ||
				NodeLinkTreeLayout.equals(buildClass) ||
				RadialTreeLayout.equals(buildClass) ||
				SquarifiedTreeMapLayout.equals(buildClass)
			)
			{
				def constructor = buildClass.getConstructor([String] as Class[])
				layout = constructor.newInstance([builder.pickPrefuseGroup(attributes) as String] as Object[])
			}
			
			//Try to instantiate the Layout with a no-parameter-constructor
			else
			{
				layout = buildClass.newInstance()
			}
		}
		
		return layout
	}
}
